// 压力情景测试
import React from 'react';
import { connect } from 'dva';
import { Form } from '@ant-design/compatible';
import '@ant-design/compatible/assets/index.css';
import { Tabs } from 'antd';
import { FirstHeaderC, AdvancedSearch, DATA_ENTRY, InputNumberC, TableC, SelectC, PrimaryC } from '../../comps';
import moment from 'moment';
import StressTest from './stressTest';
import AssetsFluidity from './assetsFluidity';
import styles from './index.less';
import { cloneDeep } from 'lodash';
import classnames from 'classnames';
const { TabPane } = Tabs;
@Form.create()
class StressSceneTest extends React.Component {
  constructor() {
    super();
    this.state = {
      nodata: true,
      isReset: false, // 是否点击重置
      activeKey: '0',
      scenesList: [], // 情景设置列表
      productCode: undefined,
      searchObj: undefined, // 查询条件
      dateEnd: undefined, // 最近有持仓的日期
      dateValue: undefined,
      sceneType: undefined, // 情景分析方式
      columns: [],
      dataSource: [],
      selectList: [],
      expandedRowKeys: [], // 表格展开行
      selectKeys: '', // 查询个券值
      countLoading: false, // 开始计算加载标记
    };
  }

  componentDidMount() {
    this.getScenesList();
  }

  changeTab = (key) => {
    this.setState({
      activeKey: key,
    });
  };

  // 查询表格
  onQuery = (e) => {
    if (!this.state.productCode) return;
    const searchObj = {
      productCode: this.state.productCode,
      sceneId: e.sceneId,
      date: moment(e.date).format('YYYY-MM-DD'),
    };
    this.setState(
      {
        searchObj,
        nodata: true,
      },
      () => {
        this.setState(
          {
            nodata: false,
          },
          () => {
            this.assetsFluidity.refresh(searchObj);
            this.changeTab('0');
          },
        );
      },
    );
  };

  // 重置
  onClear = () => {
    this.setState({
      isReset: true,
      sceneType: undefined,
      dateValue: undefined,
      productCode: undefined,
    });
  };

  // 获取下拉数据源
  getScenesList = () => {
    this.props.dispatch({
      type: 'stressTestReportSettingsM/getScenes',
      payload: {},
      callback: (data) => {
        if (!(data != undefined && data.length > 0)) return;
        this.setState({
          scenesList: data, // 初始化下拉数据
        });
        this.sceneSearch.props.form.setFieldsValue({
          sceneId: data[0].value,
        });
      },
    });
  };

  // 组合和产品改变
  handPortfolioCodeChange = (e) => {
    if (e) {
      const { info } = e;
      this.props.dispatch({
        type: 'stressSceneTestM/findProductTime',
        payload: {
          portfolioCode: info.code,
          timeRange: 1,
        },
        callback: (data) => {
          this.dateRef?.setDate(data ? moment(data) : '');
          this.setState(
            {
              dateValue: data,
              dateEnd: data,
              productCode: info.code,
            },
            () => {
              this.getBondList();
            },
          );
        },
      });
    } else {
      this.setState({ productCode: '' });
    }
  };

  // 情景分析方式改变
  sceneTypeChange = (e) => {
    this.setState(
      {
        sceneType: e,
        nodata: e == 1,
      },
      () => {
        if (e == 1) {
          this.sceneSearch.props.form.setFieldsValue({
            sceneId: this.state.scenesList[0]?.value,
          });
        }
        this.getBondList();
      },
    );
  };

  // 评估日期改变
  changeDate = (e) => {
    if (e) {
      this.setState(
        {
          dateValue: e.format('YYYY-MM-DD'),
        },
        () => {
          this.getBondList();
        },
      );
    }
  };

  // 获取个券下拉列表
  getBondList = () => {
    if (this.state.productCode && this.state.sceneType == 2 && this.state.dateValue) {
      this.setState(
        {
          expandedRowKeys: [],
          selectKeys: '',
        },
        () => {
          this.props.dispatch({
            type: `stressSceneTestM/getBondList`,
            payload: {
              productCode: this.state.productCode,
              date: this.state.dateValue,
            },
            callback: (data) => {
              this.setState({
                columns: data.columns,
                dataSource: data.dataSource,
                selectList: this.selectList(data.dataSource) || [],
              });
              this.props.form.setFieldsValue({ bondId: undefined });
              this.StressTest.setCount(false);
            },
          });
        },
      );
    }
  };

  // 整理个券下拉列表
  selectList = (data, fatherArr = []) => {
    const selectList = [];
    data &&
      data.map((item) => {
        if (item.bondType) {
          selectList.push({
            title: `${item.tradingCode}-${item.tradingName}`,
            value: item.id,
            fatherId: fatherArr, // 用于表格展开定位父级
          });
        } else if (item.children && item.children.length) {
          const arr = [...fatherArr];
          arr.push(item.id);
          selectList.push(...this.selectList(item.children, arr));
        }
      });
    return selectList;
  };

  // 个券搜索-表格展开-高亮
  bondIdChange = (e) => {
    const { selectList, expandedRowKeys } = this.state;
    const key = selectList.filter((item) => {
      return item.value == e;
    })[0].fatherId;
    let expandedId = JSON.parse(JSON.stringify(expandedRowKeys));
    expandedId = [...expandedRowKeys, ...key];
    this.setState({
      expandedRowKeys: expandedId,
      selectKeys: e,
    });
  };

  // 表格高亮
  tableRowClass = (record) => {
    return record.id == this.state.selectKeys ? 'high-light' : '';
  };
  // 展开表格
  onExpand = (expanded, record) => {
    let expandedId = this.state.expandedRowKeys;
    if (expanded) {
      expandedId.push(record.id);
    } else {
      expandedId = expandedId.filter((item) => item != record.id);
    }
    const expandedIdCopy = cloneDeep(expandedId);
    this.setState({
      expandedRowKeys: expandedIdCopy,
    });
  };

  // 开始计算
  getBondStressTestList = (e) => {
    this.setState(
      {
        countLoading: true,
      },
      () => {
        this.StressTest.getBondTableData(this.state.dataSource, this.state.productCode, this.state.dateValue);
      },
    );
  };

  // 开始计算加载标记
  changeLoading = () => {
    this.setState({
      countLoading: false,
    });
  };

  // 修改编辑状态 决定展示编辑还是保存按钮
  clickEdit = (type, record) => {
    const { dataSource } = this.state;
    let dataCopy = cloneDeep(dataSource); // 可编辑表格必须获取新的地址
    dataCopy = this.changeEdit(dataCopy, type, record.id);
    this.setState({
      dataSource: dataCopy,
    });
  };

  changeEdit = (data, type, id) => {
    const { setFieldsValue, getFieldsValue } = this.props.form;
    data &&
      data.map((item) => {
        if (item.id == id) {
          item.isEdit = type == 'edit';
          if (type == 'save' && item.bondType) {
            item.expectYieldLoss = getFieldsValue()[`${item.bondType}expectYieldLoss${id}`] || item.expectYieldLoss;
            item.expectBondLoss = getFieldsValue()[`${item.bondType}expectBondLoss${id}`] || item.expectBondLoss;
            item.expectIndexLoss = getFieldsValue()[`${item.bondType}expectIndexLoss${id}`] || item.expectIndexLoss;
          }
        } else if (item.children && item.children.length) {
          item = this.changeEdit(item.children, type, id);
        }
      });
    return data;
  };

  changeEditRowValue = (value, row, itemRowKey) => {
    const replaceTreeValue = (data) => {
      data.map((v) => {
        if (v.children) {
          replaceTreeValue(v.children);
        }
        if (v.id === row.id) v[itemRowKey] = value;
      });
      return data;
    };
    let dataCopy = cloneDeep(this.state.dataSource);
    dataCopy = replaceTreeValue(dataCopy);
    this.setState({
      dataSource: dataCopy,
    });
  };

  // 修改columns的状态
  changeColumns = (columns) => {
    const data = columns;
    if (data && data.length && data[data.length - 1].title != '操作') {
      data.push({
        key: 'operate',
        type: 'operate',
        title: '操作',
        operates: [
          {
            title: '编辑',
            rules: {
              disabled: {
                relation: 'or',
                items: [
                  { key: 'isEdit', value: [true], relation: ['='] },
                  { key: 'bondType', value: [null, undefined], relation: ['=', '='] },
                ],
              },
            },
            onClick: (record, index) => {
              this.clickEdit('edit', record);
            },
          },
          {
            title: '保存',
            rules: {
              disabled: {
                relation: 'and',
                items: [
                  { key: 'isEdit', value: [true], relation: ['!='] },
                  { key: 'bondType', value: ['rate', 'credit', 'stock'], relation: ['!=', '!=', '!='] },
                ],
              },
            },
            onClick: (record, index) => {
              this.clickEdit('save', record);
            },
          },
        ],
      });
      data.map((item) => {
        if (item.key == 'fullValue') {
          item.type = 'money';
        }
        // 预期收益率曲线上移
        if (item.key == 'expectYieldLoss') {
          item.align = 'right';
          item.render = (text, row) => {
            if (row.isEdit && (row.bondType == 'rate' || row.bondType == 'credit')) {
              return (
                <Form>
                  <InputNumberC
                    form={this.props.form}
                    dataIndex={`${row?.bondType}expectYieldLoss${row?.id}`}
                    initialValue={text}
                    precision={2}
                    onChange={(e) => {
                      this.changeEditRowValue(e, row, item.key);
                    }}
                  />
                </Form>
              );
            } else {
              return text != null && text != undefined ? text.toFixed(2) : '';
            }
          };
        }
        // 预期违约率
        if (item.key == 'expectBondLoss') {
          item.align = 'right';
          item.render = (text, row) => {
            if (row.isEdit && row.bondType == 'credit') {
              return (
                <Form>
                  <InputNumberC
                    form={this.props.form}
                    dataIndex={`${row?.bondType}expectBondLoss${row?.id}`}
                    initialValue={text}
                    precision={2}
                    onChange={(e) => {
                      this.changeEditRowValue(e, row, item.key);
                    }}
                  />
                </Form>
              );
            } else {
              return text != null && text != undefined ? text.toFixed(2) : '';
            }
          };
        }
        // 指数下跌幅度
        if (item.key == 'expectIndexLoss') {
          item.align = 'right';
          item.render = (text, row) => {
            if (row.isEdit && row.bondType == 'stock') {
              return (
                <Form>
                  <InputNumberC
                    form={this.props.form}
                    dataIndex={`${row?.bondType}expectIndexLoss${row?.id}`}
                    initialValue={text}
                    precision={2}
                    onChange={(e) => {
                      this.changeEditRowValue(e, row, item.key);
                    }}
                  />
                </Form>
              );
            } else {
              return text != null && text != undefined ? text.toFixed(2) : '';
            }
          };
        }
      });
    }
    return data;
  };

  // 个券模块
  bondRender = () => {
    const { columns, dataSource, selectList, expandedRowKeys, sceneType, countLoading } = this.state;
    const newColumns = [...this.changeColumns(columns)];
    return (
      <div className={classnames('bond-box', styles.stressSceneTest)}>
        <FirstHeaderC title={'个券设置'} />
        <div className='select-box'>
          <SelectC
            form={this.props.form} // form对象
            title='' // 显示名称
            dataIndex='bondId' // Form识别的Item ID
            dataSource={selectList}
            onChange={this.bondIdChange}
            selectWidth={300}
            filterOption={(input, option) => {
              return option.props.children.toLowerCase().indexOf(input.toLowerCase()) > -1;
            }}
          />
          <PrimaryC title='开始计算' onClick={() => this.getBondStressTestList()} loading={countLoading} />
        </div>
        <TableC
          columns={newColumns}
          dataSource={dataSource}
          rowKey='id'
          expandedRowKeys={expandedRowKeys}
          onExpand={this.onExpand}
          hidePage={true}
          rowClassName={this.tableRowClass}
          loading={this.props.loading.effects['stressSceneTestM/getBondList']}
        />
        <FirstHeaderC title={'压力测试'} topHeight={true} />
        <StressTest sceneType={sceneType} onRef={(ref) => (this.StressTest = ref)} changeLoading={this.changeLoading} />
      </div>
    );
  };

  render() {
    const { scenesList, activeKey, searchObj, nodata, dateValue, sceneType, dateEnd } = this.state;
    const sceneTypeList = [
      {
        title: '设置情景',
        value: 1,
      },
      {
        title: '设置个券',
        value: 2,
      },
    ];
    const searchProps = {
      dataSource: [
        {
          dataIndex: 'productCode',
          title: '产品',
          type: DATA_ENTRY.PRODUCTLIST,
          allowClear: true,
          dataType: 2,
          showSearch: true,
          rules: [{ required: true, message: '请选择产品!' }],
          onChange: (e) => this.handPortfolioCodeChange(e),
        },
        {
          dataIndex: 'date',
          title: '评估日期',
          type: DATA_ENTRY.SINGLEDATE,
          initialValue: dateValue ? moment(dateValue) : '',
          rules: [{ required: true, message: '请选择评估日期!' }],
          disableEnd: moment(dateEnd).add(1, 'day'),
          onRef: (ref) => (this.dateRef = ref),
          onChange: (e) => {
            this.changeDate(e);
          },
        },
        {
          dataIndex: 'sceneType',
          title: '情景分析方式',
          type: DATA_ENTRY.SELECT,
          allowClear: false,
          dataSource: sceneTypeList,
          rules: [{ required: true, message: '情景分析方式!' }],
          onChange: (e) => this.sceneTypeChange(e),
        },
        {
          dataIndex: 'sceneId',
          title: '情景名称',
          type: DATA_ENTRY.SELECT,
          allowClear: false,
          dataSource: scenesList.map((item) => {
            const obj = {
              title: item.display,
              value: item.value,
            };
            return obj;
          }),
          rules: [{ required: true, message: '情景名称!' }],
          hide: !(sceneType == 1),
        },
      ],
      allowQuery: sceneType != 2,
      allowClear: true,
      onRef: (ref) => {
        this.sceneSearch = ref;
      },
      onQuery: this.onQuery,
      onClear: this.onClear,
    };
    console.log('render>>>>>>>', this.state.expandedRowKeys);
    return (
      <div className={styles.stressSceneTest}>
        <AdvancedSearch {...searchProps} />
        {sceneType == 2 ? (
          this.bondRender()
        ) : !nodata ? (
          <div>
            <div className='module-box'>
              <FirstHeaderC title={'压力测试'} />
              <Tabs onChange={this.changeTab} activeKey={activeKey} type='card'>
                <TabPane tab='轻度假设' key='0'>
                  <StressTest searchObj={searchObj} sceneType={sceneType} activeKey='0' onRef={(ref) => (this.StressTest = ref)} />
                </TabPane>
                <TabPane tab='中度假设' key='1'>
                  <StressTest searchObj={searchObj} sceneType={sceneType} activeKey='1' onRef={(ref) => (this.StressTest = ref)} />
                </TabPane>
                <TabPane tab='重度假设' key='2'>
                  <StressTest searchObj={searchObj} sceneType={sceneType} activeKey='2' onRef={(ref) => (this.StressTest = ref)} />
                </TabPane>
              </Tabs>
            </div>
            <div>
              <FirstHeaderC title={'流动性分析'} />
              <AssetsFluidity onRef={(ref) => (this.assetsFluidity = ref)} />
            </div>
          </div>
        ) : (
          ''
        )}
      </div>
    );
  }
}
export default connect(({ stressTestReportSettingsM, stressSceneTestM, loading }) => ({
  stressTestReportSettingsM,
  stressSceneTestM,
  loading,
}))(StressSceneTest);
